<?php
class StringTools{
    /**
     * 将一个数格式化成，千位加,的格式
     * @param $pNumber 需要格式话的数字
     * @return 格式化好的字符串
     */
    public static function formatDigital($pNumber){
        $ret = "";
        $int = floor($pNumber);
        $ret = substr($pNumber-$int, 1);
        while($int>=1000)
        {
            $ret = ",".substr("t".(1000+($int%1000)), 2).$ret;
            $int = ($int-$int%1000)/1000;
        }
        return $int.$ret;
    }
    
    /**
     * 返回一个字符串左面的子串
     * @param $pString 字符串，父串
     * @param $pLength 需要取的字符串的长度
     * @return 取得的字符串
     */
    public static function left($pString, $pLength){
    	$strlenth	=	0;
    	$out		=	'';
    	preg_match_all("/[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xff][\x80-\xbf]{3}/", $pString, $match);
    	foreach($match[0] as $v){
    		preg_match("/[\xe0-\xef][\x80-\xbf]{2}/",$v, $matchs);
    		if(!empty($matchs[0])){
    			$strlenth	+=	1;
    		}elseif(is_numeric($v)){
    			$strlenth	+=	0.545;
    		}else{
    			$strlenth	+=	0.475;
    		}

    		if($strlenth>$pLength){
    			break;
    		}

    		$output	.=	$v;
    	}
    	return $output;
    }
    
    /**
     * 返回一个字符串右面的子串
     * @param $pString 字符串，父串
     * @param $pLength 需要取的字符串的长度
     * @return 取得的字符串
     */
    public static function right($pString, $pLength){
        $str_length = self::length($pString);
        if($str_length<=$pLength)
        {
            return $pString;
        }
        else
        {
            return self::msubstr($pString, $str_length-$pLength, $pLength);
        }
    }
    
    /**
     * 返回一个字符串来表示时间
     * @param $pFlag 标志位来说明返回的时间字符串的格式，10:YYYY-MM-DD; 19:YYYY-MM-DD HH:MM:SS
     * @param $pTimeStamp 如果提供时间戳则根据时间戳转换，否则去当前时间
     * @return 取得的时间字符串
     */
    public static function getDateTime($pFlag=10, $pTimeStamp=-1){
        $date_format = "Y-m-d";
        switch($pFlag){
            case 8://20030604
                $date_format = "Ymd";
                break;
            case 10://2003-06-04
                $date_format = "Y-m-d";
                break;
            case 14://20030604201300
                $date_format = "YmdHis";
                break;
            case 19://2003-06-04 20:13:00
                $date_format = "Y-m-d H:i:s";
                break;
            case 21:////2003年06月04日
                $date_format = "Y年m月d日";
                break;
        }
        if($pTimeStamp>=0){
            return date($date_format, $pTimeStamp);
        }
        else{
            return date($date_format);
        }
    }
    
   /**
     * 返回一个字符串时间的时间戳
     * @param $pDateString 时间字符串，10:YYYY-MM-DD; 19:YYYY-MM-DD HH:MM:SS
     * @return 转换后的时间戳，默认当前时间戳
     */
   public static function time($pDateString=""){
        switch(strlen($pDateString)){
            case 0:
                return time();
                break;
            case 8://20030604
                $year = substr($pDateString, 0, 4);
                $month = substr($pDateString, 4, 2);
                $day = substr($pDateString, 6, 2);
                return mktime(0, 0, 0, $month, $day, $year);
                break;
            case 10://2003-06-04
                $dateArr = explode("-",$pDateString);
                return mktime(0, 0, 0, $dateArr[1], $dateArr[2], $dateArr[0]);
                break;
            case 14://20030604201300
                $year   = substr($pDateString,  0, 4);
                $month  = substr($pDateString,  4, 2);
                $day    = substr($pDateString,  6, 2);
                $hour   = substr($pDateString,  8, 2);
                $minute = substr($pDateString, 10, 2);
                $second = substr($pDateString, 12, 2);
                return mktime($hour, $minute, $second, $month, $day, $year);
                break;
            case 19://2003-06-04 20:13:00
                $arr = explode(" ",$pDateString);
                $dateArr = explode("-",$arr[0]);
                $timeArr = explode(":",$arr[1]);
                return mktime($timeArr[0],$timeArr[1],$timeArr[2],$dateArr[1],$dateArr[2],$dateArr[0]);
                break;
            default:
                return time();
        }
    }
    
    /**
     * 将一个十六进制得字符串转换成二进制表示
     * @author changwei
     * @createTime 2004-04-08
     * @param $pHexString 十六进制得字符串
     * @return 转换后得二进制字符串
     */
   public static function Hex2Bin($pHexString){
        $hexLenght = strlen($pHexString);
        // only hex numbers is allowed
        if ($hexLenght % 2 != 0 || preg_match("/[^\da-fA-F]/",$pHexString))
            return FALSE;

        unset($binString);
        for ($x = 1; $x <= $hexLenght/2; $x++){
            $binString .= chr(hexdec(substr($pHexString, 2*$x-2, 2)));
        }

        return $binString;
    }
    /**
     * 截取全角和半角混合的字符串左边以避免乱码
     * @author changwei
     * @createTime 2004-04-08
     * @param $pString 需要截断的字符串
     * @param $pLength 允许字符串显示的最大长度
     * @return 截断的字符串
     */
   public static function CHSLeft($pString, $pLength){
        $rString = "";
        if (self::length($pString) > $pLength)
        {
            for($i=0; $i < $pLength; $i++)
                if (ord($pString[$i]) > 128)
                    $i++;
            $rString = self::msubstr($pString, 0, $i,"utf-8",true);
        }
        else
        {
            $rString = $pString;
        }
        return $rString;
    }
    
    /**
     * 判断一个字符串是否是整数
     * @author changwei
     * @createTime 2004-05-17
     * @param $pString 需要判断的字符串
     * @return 布尔值
     */
    public static function isNumber($pString){
        $length = self::length($pString);
        //空字符串返回不是整数
        if($length==0)
        {
            return false;
        }
        for($i=0;$i<$length;$i++)
        {
            //根据ASCII判断是否字符串中的每个字符都是数字
            if($pString[$i]<"0" || $pString[$i]>"9")
            {
                return false;
            }
        }
        return true;
    }
    
   /**
     * 讲数字转换成中文大写
     * @param $data 需要判断的字符串
     * @return 布尔值
     */
    public static function money2cn($data){
        $capnum = array("零","壹","贰","叁","肆","伍","陆","柒","捌","玖");
        $capdigit = array("","拾","佰","仟");
        $subdata = explode(".",$data);
        $yuan = $subdata[0];
        $j = 0;
        $nonzero = 0;
        for($i=0;$i<strlen($subdata[0]);$i++)
        {
            if(0==$i)
            { //确定个位
                if($subdata[1])
                {
                    $cncap=(substr($subdata[0],-1,1)!=0)?"元":"元零";
                }
                else
                {
                    $cncap="元";
                }
            }
            if(4==$i){ $j=0;  $nonzero=0; $cncap="万".$cncap; } //确定万位
            if(8==$i){ $j=0;  $nonzero=0; $cncap="亿".$cncap; } //确定亿位
            $numb=substr($yuan,-1,1); //截取尾数
            $cncap=($numb)?$capnum[$numb].$capdigit[$j].$cncap:(($nonzero)?"零".$cncap:$cncap);
            $nonzero=($numb)?1:$nonzero;
            $yuan=substr($yuan,0,strlen($yuan)-1); //截去尾数
            $j++;
        }

        if($subdata[1])
        {
            $chiao=(substr($subdata[1],0,1))?$capnum[substr($subdata[1],0,1)]."角":"零";
            $cent=(substr($subdata[1],1,1))?$capnum[substr($subdata[1],1,1)]."分":"零分";
        }
        $cncap .= $chiao.$cent."整";
        $cncap=preg_replace("/(零)+/","\\1",$cncap); //合并连续“零”
        return $cncap;
    }
    
    public static function string2Array($pString){
        $result = array();
        for($i=0; $i<self::length($pString); $i++)
            $result[] = $pString[$i];
        return $result;
    }
    
   public static function randString($pLength, $pInclude="dsS", $pUserDefine=""){
        $all["d"] = array(0,1,2,3,4,5,6,7,8,9);
        $all["s"] = array("a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z");
        $all["S"] = array("A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z");
        $all["u"] = self::string2Array($pUserDefine);
        $letter = $all["u"];

        for($i=0; $i<strlen($pInclude); $i++)
            $letter = array_merge($letter, $all[$pInclude[$i]]);
        //print_r($letter);
        $size = count($letter);
        for($i=0; $i<$pLength; $i++){
            $index = rand(0, 1000*$size);
            $index = $index%$size;
            $result .= $letter[$index];
        }
        return $result;
    }
    
    public static function trimHTMLTag($pString){
        $pString = preg_replace("#<br */?>#msi", "\r\n", $pString);
        return preg_replace("#<[^<>]+>#msi", "", $pString);
    }

    public static function unifyLength($pString, $pLength, $pChar='0'){
        if(strlen($pString)>$pLength){
            return $pString;
        }else{
            $pre = self::repeat($pChar, $pLength);
            return self::right($pre.$pString, $pLength);
        }
    }

    public static function trimHtmlSpace($pString){
        $string = self::trimHead($pString);
        return self::trimTail($string);
    }

    public static function trimTail($pString){
        $arr = explode('&nbsp;', $pString);
        $length = count($arr);
        for($i=$length-1; $i>-1; $i--){
            $arr[$i] = trim($arr[$i], " \r\v\n\f\t");
            if($arr[$i]==""){
                unset($arr[$i]);
            }
            else{
                break;
            }
        }
        return implode('&nbsp;', $arr);
    }

    public static function trimHead($pString){
        $arr = explode('&nbsp;', $pString);
        $length = count($arr);
        for($i=0; $i<$length; $i++){
            $arr[$i] = trim($arr[$i], " \r\v\n\f\t");
            $arr[$i] = preg_replace("#(\xA3\xA0)|(\xA1\xA1)|(\xAA\xA5)#msi", "", $arr[$i]);
            if($arr[$i]==""){
                unset($arr[$i]);
            }else{
                break;
            }
        }
        return implode('&nbsp;', $arr);
    }

    public static function htmlspecialchars_decode($pString){
        $result = $pString;
        $result = str_replace("&lt;", "<", $result);
        $result = str_replace("&gt;", ">", $result);
        $result = str_replace("&quot;", '"', $result);
        $result = str_replace("&amp;", "&", $result);
        return $result;
    }

    public static function filterParagraph($pString){
        $result = $pString;
        $result = preg_replace("#<br\s*/?\s*>\n?#msi", "\n", $result);
        $result = preg_replace("#<(/?b)>#msi", "-\\1-", $result);
        $result = self::trimHTMLTag($result);
        $result = preg_replace("#-(/?b)-#msi", "<\\1>", $result);
        return self::trimHtmlSpace($result, " \r\v\n\f\t");
    }
	//过滤脚本代码
	public static function cleanJs($text) {
	    $text	=	trim($text);
	    //$text	=	mysql_escape_string($text);
	    //完全过滤注释
	    $text	=	preg_replace('/<!--?.*-->/','',$text);
	    //完全过滤动态代码
	    $text	=	preg_replace('/<\?|\?>/','',$text);
	    //完全过滤js
	    $text	=	preg_replace('/<script?.*\/script>/','',$text);
	    //过滤多余html
	    $text	=	preg_replace('/<\/?(html|head|meta|link|base|body|title|script|form|iframe|frame|frameset)[^><]*>/i','',$text);
	    //过滤on事件lang js
	    while(preg_match('/(<[^><]+)(lang|onfinish|onmouse|onexit|onerror|onkey|onload|onchange|onfocus|onblur)[^><]+/i',$text,$mat)) {
	        $text=str_replace($mat[0],$mat[1],$text);
	    }
	    while(preg_match('/(<[^><]+)(window\.|js:|javascript:|about:|file:|document\.|vbs:|vbscript:|cookie)([^><]*)/i',$text,$mat)) {
	        $text=str_replace($mat[0],$mat[1].$mat[3],$text);
	    }
	    //过滤多余空格
	    $text	=	str_replace('  ',' ',$text);
	    return $text;
	}
	
	//纯文本输出
	public static function text($text) {
	    $text	=	self::cleanJs($text);
	    $text	=	strip_tags($text);
	    $text	=	htmlspecialchars($text,ENT_NOQUOTES);
	    return $text;
	}
	
	//输出安全的html
	public static function html($text) {
	    $text	=	self::cleanJs($text);
	    return $text;
	}
	
	public static function selfCode($string,$type="string"){
		$filter = new Security($type);
		return $filter->inputFilter($string);
	}
	
	//加密函数
	public static function Encrypt($txt,$key=null) {
		$txt = base64_encode($txt);
	    if(empty($key)) $key = $_ENV ['config']->getSetting ( 'site_config', 'Security', 'SECURE_CODE' );
		PLoader::import('helper.base.Code',PATH_LIBRARIES);
		PLoader::import('helper.base.Encrypt',PATH_LIBRARIES);
		$a = new Encrypt($txt,$key);
 		return $a->returnCode();
	}
	
	//解密函数
	public static function Decrypt($txt,$key = null) {
	    if(empty($key)) $key = $_ENV ['config']->getSetting ( 'site_config', 'Security', 'SECURE_CODE' );
		PLoader::import('helper.base.Code',PATH_LIBRARIES);
		PLoader::import('helper.base.Decrypt',PATH_LIBRARIES);
		$a = new Decrypt($txt,$key);
 		$result = $a->returnCode();	
 		return base64_decode($result);
 		
	}
	/**
	 * 文字转换
	 * @param  $pFrom 源编码 BIG5|GB2312
	 * @param  $pTo 目标编码 PinYin|BIG5|GB2312|UTF8|UNICODE
	 * @param  $pString 待转换的字符串
	 */	
	public static function iconv($pFrom,$pTo,$pString){
		PLoader::import('helper.chinese.Chinese',PATH_LIBRARIES);
        $Chinese = new Chinese(strtoupper($pFrom), strtoupper($pTo), $pString);
        var_dump($chinese);
	    return $Chinese->ConvertIT();
    }
    
	/**
	 * msubstr
	 * 字符串截断。支持中文和utf-8编码
	 * @param mixed $str
	 * @param int $start
	 * @param mixed $length
	 * @param string $charset
	 * @param mixed $suffix
	 * @access public
	 * @return void
	 */
	public static function msubstr($str, $start=0, $length, $charset="utf-8", $suffix=true) {
	    if(function_exists("mb_substr"))
	        $slice = mb_substr($str, $start, $length, $charset);
	    elseif(function_exists('iconv_substr')) {
	        $slice = iconv_substr($str,$start,$length,$charset);
	    }else{
		    $re['utf-8']   = "/[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xff][\x80-\xbf]{3}/";
		    $re['gb2312'] = "/[\x01-\x7f]|[\xb0-\xf7][\xa0-\xfe]/";
		    $re['gbk']	  = "/[\x01-\x7f]|[\x81-\xfe][\x40-\xfe]/";
		    $re['big5']	  = "/[\x01-\x7f]|[\x81-\xfe]([\x40-\x7e]|\xa1-\xfe])/";
		    preg_match_all($re[$charset], $str, $match);
		    $slice = join("",array_slice($match[0], $start, $length));
	    }
	    if($suffix && $str != $slice) return $slice."...";
	    return $slice;
	}	
	
	//取得字符串的长度，包括中英文。
	public static function length($text){
	  if (function_exists('mb_substr')){
	    $length = mb_strlen($text,'UTF-8');
	  } 
	  elseif (function_exists('iconv_substr')){
	    $length = iconv_strlen($text,'UTF-8');
	  } else{
	  	$text = self::safeEncoding($text,'UTF-8');
	    preg_match_all("/[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|\xe0[\xa0-\xbf][\x80-\xbf]|[\xe1-\xef][\x80-\xbf][\x80-\xbf]|\xf0[\x90-\xbf][\x80-\xbf][\x80-\xbf]|[\xf1-\xf7][\x80-\xbf][\x80-\xbf][\x80-\xbf]/", $text, $ar);  
	    $length = count($ar[0]);
	  }
	  return $length;
	}
	
	//识别汉字编码,如果引用通告发过来的是gb2312的编码的话,需要可以识别并完成编码转换
	public static function safeEncoding($string,$outEncoding = 'UTF-8') {
	    $encoding = "UTF-8";
	    for($i=0;$i<strlen($string);$i++) {
	        if(ord($string{$i})<128)
	            continue;
	
	        if((ord($string{$i})&224)==224) {
	        //第一个字节判断通过
	            $char = $string{++$i};
	            if((ord($char)&128)==128) {
	            //第二个字节判断通过
	                $char = $string{++$i};
	                if((ord($char)&128)==128) {
	                    $encoding = "UTF-8";
	                    break;
	                }
	            }
	        }
	        if((ord($string{$i})&192)==192) {
	        //第一个字节判断通过
	            $char = $string{++$i};
	            if((ord($char)&128)==128) {
	            //第二个字节判断通过
	                $encoding = "GB2312";
	                break;
	            }
	        }
	    }
	
	    if(strtoupper($encoding) == strtoupper($outEncoding))
	        return $string;
	    else
	        return iconv($encoding,$outEncoding,$string);
	}
	
    /**
     * 如果路径后面没有加分隔符，则在给定的路径后面添加一个分隔符
     * @param $pPath 路径
     * @return 返回添加了分隔符的路径
     */
    public static function getValidPath($pPath){
        //如果没有在后面加上路径分隔符，则加上
        if(self::right($pPath, 1)!= "/")
        {
            $pPath .= "/";
        }
        return $pPath;
    }
}
